﻿using System;
using System.Web;
using System.IO;
using System.Net;
using System.Xml;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using StripeOne.Core.S1Cache;
using StripeOne.Core.S1Tools;

namespace StripeOne.Core.XmlConfig
{
	public class XmlTool
	{

		#region GetField's [public]

		public static string GetField(XmlNode node, string path)
		{
			return GetField(node, path, true);
		}
		public static string GetField(XmlNode node, string path, bool abortLogOutpu)
		{
			return GetNodeValue(node, path);
		}

		public static string[] GetFields(XmlNode node, string path)
		{
			return GetFields(node, path, true);
		}
		public static string[] GetFields(XmlNode node, string path, bool abortLogOutpu)
		{
			return GetNodeValues(node, path);
		}

		#endregion

		#region GetNodeValue's [private]

		private static string GetNodeValue(XmlNode node, string path)
		{
			if(node == null) return string.Empty;

			try
			{
				if(path.Length > 0)
				{
					node = node.SelectSingleNode(path);
				}
				if(node != null)
				{
					if((((node is XmlAttribute) || (node is XmlText)) || (node is XmlCDataSection)) && (node.Value != null))
					{
						return node.Value.Trim();
					}
					if(node is XmlElement)
					{
						return GetNodeValue(node, "text()");
					}
				}
			}
			catch
			{
				return string.Empty;
			}
			return string.Empty;
		}
        private static string[] GetNodeValues(XmlNode node, string path)
		{
			if(node == null) return new string[] { };

			XmlNodeList list = node.SelectNodes(path);
			string[] strArray = new string[list.Count];
			for(int i = 0; i < strArray.Length; i++)
			{
				strArray[i] = GetNodeValue(list[i], "");
			}
			return strArray;
		}

		#endregion

		#region GetXmlNode [public]

		public static XmlNodeList GetXmlNodeList(XmlElement xmlDoc, string path)
		{
			return GetXmlNodeList(xmlDoc, path, true);
		}
		public static XmlNodeList GetXmlNodeList(XmlElement xmlDoc, string path, bool abortLogOutput)
		{
			if(xmlDoc == null || String.IsNullOrEmpty(path)) return null;
			try
			{
				return xmlDoc.SelectNodes(path);
			}
			catch
			{
				return null;
			}
		}

		public static XmlNode GetXmlNode(XmlElement xmlDoc, string path)
		{
			return GetXmlNode(xmlDoc, path, true);
		}
		public static XmlNode GetXmlNode(XmlElement xmlDoc, string path, bool abortLogOutput)
		{
			if(xmlDoc == null || String.IsNullOrEmpty(path)) return null;
			try
			{
				XmlNode xmlNode = xmlDoc.SelectSingleNode(path);
				if(xmlNode == null && path.ToLower().Equals(xmlDoc.Name.ToLower()))
				{
					xmlNode = xmlDoc;
				}
				return xmlNode;
			}
			catch
			{
				return null;
			}
		}

		#endregion

		#region GetXmlXmlElement [public]


		public static XmlElement GetXmlElement(XmlDocument xmlDoc, string section)
		{
			try
			{
				return (XmlElement)GetXmlNode(xmlDoc.DocumentElement, section);
			}
			catch
			{
				return null;
			}
		}
		public static XmlElement GetXmlElement(XmlElement xmlDoc, string section)
		{
			try
			{
				return (XmlElement)GetXmlNode(xmlDoc, section);
			}
			catch
			{
				return null;
			}
		}

		#endregion

		#region GetXmlDocument [public]


		public static XmlDocument GetXmlDocument(string Url, Encoding encoding)
		{
			return GetXmlRequestNoCache(Url, encoding);
		}

		public static XmlDocument GetXmlDocument(string webUrl, int cacheTime)
		{
			return GetXmlDocument(webUrl, false, cacheTime);
		}
		public static XmlDocument GetXmlDocument(string webUrl, bool isLocalFile, int cacheTime)
		{
			return GetXmlRequest(webUrl, isLocalFile, cacheTime);
		}

		public static XmlElement GetXmlElement(string webUrl, string section, int cacheTime)
		{
			return GetXmlElement(GetXmlRequest(webUrl, false,  cacheTime), section);
		}
		public static XmlElement GetXmlElement(string webUrl, string section, bool isLocalFile, int cacheTime)
		{
			return GetXmlElement(GetXmlRequest(webUrl, isLocalFile, cacheTime), section);
		}
		public static XmlElement GetXmlElement(string webUrl, string section, Encoding encoding, int cacheTime)
		{
			return GetXmlElement(GetXmlRequest(webUrl, encoding, false, cacheTime), section);
		}
		public static XmlElement GetXmlElement(string webUrl, string section, Encoding encoding, bool isLocalFile, int cacheTime)
		{
			return GetXmlElement(GetXmlRequest(webUrl, encoding, isLocalFile, cacheTime), section);
		}

		#endregion

		#region GetXmlRequest [private]

		private static XmlDocument GetXmlRequest(string webUrl, int cacheTime)
		{
			return GetXmlRequest(webUrl, Encoding.Default, false,  cacheTime);
		}
		private static XmlDocument GetXmlRequest(string webUrl, bool isLocalFile, int cacheTime)
		{
			return GetXmlRequest(webUrl, Encoding.Default, isLocalFile, cacheTime);
		}

		private static XmlDocument GetXmlRequest(string webUrl, Encoding encoding, bool isLocalFile, int cacheTime)
		{
			string key = "XmlDocument_" + webUrl;

			object obj = S1Cache.S1Cache.GetObject(key);
			if(obj != null && obj is XmlDocument)
			{
				return (XmlDocument)obj;
			}

			// No Cached
			XmlDocument doc;
			if(isLocalFile)
			{
				doc = GetLocalXml(webUrl);
                S1Cache.S1Cache.Add(doc, key, cacheTime);
			}
			else
			{
				doc = GetXmlRequestNoCache(webUrl, encoding);
                S1Cache.S1Cache.Add(doc, key, cacheTime);
			}
			return doc;
		}

		#region GetXmlRequest [GetLocalXml]
		
        private static XmlDocument GetLocalXml(string webUrl)
		{
			XmlDocument xmlDoc = new XmlDocument();
			try
			{
				xmlDoc.Load(webUrl);
			}
			catch{  }
			return xmlDoc;
		}
		
        #endregion

		#region GetXmlRequest [GetXmlRequestNoCache]

		private static XmlDocument GetXmlRequestNoCache(string webUrl, Encoding encoding)
		{
			XmlDocument xmlDoc = new XmlDocument();
			WebResponse response = null;

			try
			{
				WebRequest request = WebRequest.Create(webUrl);
				response = request.GetResponse();

				using(Stream stream = response.GetResponseStream())
				{
					using(StreamReader reader = new StreamReader(stream, encoding))
					{
						xmlDoc.Load(reader);
					}
				}
			}
			catch
			{}
			finally
			{
				if(response != null) response.Close();
			}
			return xmlDoc;
		}
		
        #endregion

		#endregion
	}
}